#![no_std]

use core::mem::size_of;

pub struct RawPerdata<T> {
    offset: *mut T,
    free: fn(usize),
}

impl<T> RawPerdata<T> {
    pub fn new<F>(p: T, cnt: usize, alloc: F, free: fn(usize)) -> Self
    where
        F: Fn(usize) -> usize,
    {
        let offs = alloc(cnt * size_of::<T>());
        if offs == 0 {
            panic!("raw_perdata: Out of memory");
        }

        let perdata = Self {
            offset: offs as *mut T,
            free,
        };

        unsafe {
            for i in 0..cnt {
                let ptr = perdata.offset.add(i);
                ptr.copy_from(&p, 1);
            }
        }

        perdata
    }

    #[inline(always)]
    pub fn get(&self, index: usize) -> &T {
        unsafe { (self.offset.add(index)).as_ref().unwrap() }
    }

    #[inline(always)]
    pub fn get_mut(&mut self, index: usize) -> &mut T {
        unsafe { (self.offset.add(index)).as_mut().unwrap() }
    }
}

impl<T> Drop for RawPerdata<T> {
    fn drop(&mut self) {
        (self.free)(self.offset as usize)
    }
}
